package tools

import (
	"database/sql"
	"fmt"
	"gdshop-font-api-go/app/response/BaseResp"
	"gdshop-font-api-go/library/response"
	"gdshop-font-api-go/library/tools/genids"
	"github.com/gogf/gf/crypto/gmd5"
	"github.com/gogf/gf/frame/g"
	"github.com/gogf/gf/net/ghttp"
	"github.com/gogf/gf/util/gconv"
	"github.com/gogf/gf/util/grand"
	"github.com/hprose/hprose-golang/rpc"
	_ "github.com/hprose/hprose-golang/rpc/fasthttp"
	"github.com/xxtea/xxtea-go/xxtea"
	"math"
	"regexp"
	"strconv"
	"strings"
	"time"
)

func EncryptPassword(password string, passwordSalt string) string {
	return gmd5.MustEncrypt(gmd5.MustEncrypt(password) + gmd5.MustEncrypt(passwordSalt))
}

var vcodeKeyName = "gdshopVCode"

// 获取短信验证码 数字
func GetVCode(mobile string) string {
	length := 6
	conn := g.Redis().Conn()
	defer conn.Close()
	code := grand.Digits(length)
	conn.Do("HSET", vcodeKeyName, mobile, code)
	return code
}

// 验证 短信验证码
func VerifyVCode(mobile string, code string) bool {
	// 单元测试验证码
	if g.Cfg().GetBool("site.Debug") == true {
		return true
	}
	conn := g.Redis().Conn()
	defer conn.Close()
	v, _ := conn.DoVar("HGET", vcodeKeyName, mobile)
	return v.String() == code
}

var VCodeOftenName = "VCodeOftenName"

// 设置发送时间
func SetVCodeOften(mobile string) {
	conn := g.Redis().Conn()
	defer conn.Close()
	conn.Do("HSET", VCodeOftenName, mobile, time.Now().Unix())
}

// 检查验证码发送是否频繁，过期时间 60 秒 false=可以发送
func CheckVCodeOften(mobile string) bool {
	if g.Cfg().GetBool("site.Debug") == true {
		return false
	}
	conn := g.Redis().Conn()
	defer conn.Close()
	v, _ := conn.DoVar("HGET", VCodeOftenName, mobile)
	often := g.Cfg().GetInt64("site.VCodeOften", 60)
	if time.Now().Unix() > (v.Int64() + often) {
		return false
	} else {
		return true
	}
}

// 获取分页信息
func GetPageInfo(totalRows int, pageIndex int, pageSize int) BaseResp.PageInfo {
	totalPage := int(math.Ceil(float64(totalRows) / float64(pageSize)))
	return BaseResp.PageInfo{
		HasMore:     totalPage > pageIndex,
		PageIndex:   pageIndex,
		PageSize:    pageSize,
		TotalCount:  totalRows,
		TotalPage:   totalPage,
		IsFirstPage: pageIndex < 2,
		IsLastPage:  pageIndex > totalPage,
	}
}

func GetGoodsThumbs(thumbs string) []string {
	return strings.Split(thumbs, ",")
}

// 如果查询不到数据时，返回的处理，必须有错误才调用本方法
// err 错误
// message 返回消息
// isSuccess true返回成功，false返回失败
func GetErrNoRowsResponse(err error, message string, isSuccess bool) *response.JsonResponse {
	if err == sql.ErrNoRows {
		if isSuccess == true {
			return response.SuccessByRequestMessage(nil, message)
		} else {
			return response.FailByRequestMessage(nil, message)
		}
	}
	// 其他错误，必须返回错误
	return response.FailByRequestMessage(nil, err.Error())
}

func Decimal(value float64) float64 {
	value, _ = strconv.ParseFloat(fmt.Sprintf("%.2f", value), 64)
	return value
}

func GetBackClient() *ghttp.Client {
	return g.Client()
}

// FloatRound 截取小数位数
func FloatRound(f float64, n int) float64 {
	format := "%." + strconv.Itoa(n) + "f"
	res, _ := strconv.ParseFloat(fmt.Sprintf(format, f), 64)
	return res
}

//表情解码
func UnicodeEmojiDecode(s string) string {
	//emoji表情的数据表达式
	re := regexp.MustCompile("\\[[\\\\u0-9a-zA-Z]+\\]")
	//提取emoji数据表达式
	reg := regexp.MustCompile("\\[\\\\u|]")
	src := re.FindAllString(s, -1)
	for i := 0; i < len(src); i++ {
		e := reg.ReplaceAllString(src[i], "")
		p, err := strconv.ParseInt(e, 16, 32)
		if err == nil {
			s = strings.Replace(s, src[i], string(rune(p)), -1)
		}
	}
	return s
}

//表情转换
func UnicodeEmojiCode(s string) string {
	ret := ""
	rs := []rune(s)
	for i := 0; i < len(rs); i++ {
		if len(string(rs[i])) == 4 {
			u := `[\u` + strconv.FormatInt(int64(rs[i]), 16) + `]`
			ret += u

		} else {
			ret += string(rs[i])
		}
	}
	return ret
}

func GetRpcClient() rpc.Client {
	client := rpc.NewClient(g.Cfg().GetString("rpc.url"))
	client.SetTimeout(3 * time.Second)
	client.SetRetry(3)
	client.AddBeforeFilterHandler(func(request []byte, context rpc.Context,
		next rpc.NextFilterHandler) (response []byte, err error) {
		// 发送前加密
		response, err = next(xxtea.Encrypt(request, g.Cfg().GetBytes("rpc.key")), context)
		return
	})

	return client
}

// DuplicateInArray 是否重复，不重复返回 -1
func DuplicateInArray(arr []int) int {
	visited := make(map[int]bool, 0)
	for i := 0; i < len(arr); i++ {
		if visited[arr[i]] == true {
			return arr[i]
		} else {
			visited[arr[i]] = true
		}
	}
	return -1
}

// GetOrderNo orderType 类型 1=主订单，2=子订单，3=提现
func GetOrderNo(orderType int) (string, error) {
	orderNo, idErr := genids.ToolsGetNextId()
	if idErr != nil {
		return "", idErr
	}
	orderTypeStr := "M"
	if orderType == 2 {
		orderTypeStr = "S"
	}
	if orderType == 3 {
		orderTypeStr = "W"
	}
	return gconv.String(time.Now().Year()) + orderTypeStr + gconv.String(orderNo), nil
}
